﻿using Microsoft.Extensions.Logging;
using SerilogLog = Serilog.Log;
using SerilogLogger = Serilog.ILogger;

namespace Grow.Log.Serilog.Logging
{
    public class Logger : ILogger
    {
        private readonly LogOptions _logOptions;
        private readonly SerilogLogger _serilogLogger;
        public IExternalScopeProvider ExternalScopeProvider { get; set; }
        public Logger(string name, IExternalScopeProvider externalScopeProvider, LogOptions logOptions)
        {

            ExternalScopeProvider = externalScopeProvider;
            _logOptions = logOptions;
            _serilogLogger = SerilogLog.Logger.ForContext("Grow", name);
        }


        public IDisposable? BeginScope<TState>(TState state) where TState : notnull
        {
            return ExternalScopeProvider.Push(state);
        }

        public bool IsEnabled(LogLevel logLevel)
        {
            return _logOptions.LogLevel switch
            {
                LogLevelEnum.Trace => logLevel != LogLevel.Trace,
                LogLevelEnum.Debug => logLevel != LogLevel.Debug,
                LogLevelEnum.Information => logLevel != LogLevel.Information,
                LogLevelEnum.Warning => logLevel != LogLevel.Warning,
                LogLevelEnum.Error => logLevel != LogLevel.Error,
                LogLevelEnum.Critical => logLevel != LogLevel.Critical,
                _ => logLevel != LogLevel.Debug,
            };
        }

        public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter)
        {
            if (!IsEnabled(logLevel))
            {
                return;
            }
            string message = formatter(state, exception);
            switch (logLevel)
            {
                case LogLevel.Trace:
                    _serilogLogger.Verbose(message);
                    break;
                case LogLevel.Debug:
                    _serilogLogger.Debug(message);
                    break;
                case LogLevel.Information:
                    _serilogLogger.Information(message);
                    break;
                case LogLevel.Warning:
                    _serilogLogger.Warning(message);
                    break;
                case LogLevel.Error:
                    _serilogLogger.Error(message);
                    break;
                case LogLevel.Critical:
                    _serilogLogger.Fatal(message);
                    break;
                case LogLevel.None:
                    break;
                default:
                    _serilogLogger.Information($"遇到未知的日志级别 {logLevel}, 使用Info级别写入日志。{message}");
                    break;
            }
        }



    }
}